﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Text;
using Dry.DbInterpreter;
using Microsoft.Practices.EnterpriseLibrary.Data;

namespace Dry.Generators
{
    public class AscxGenerator :  GeneratorBase
    {
        private static string _tablePrefix;

        public static GeneratorFeedback CreateFile(string strTableName, string tablePrefix)
        {
            GeneratorFeedback generatorFeedback = new GeneratorFeedback();

            _tablePrefix = tablePrefix;

            int lines = 0;

            string userControlName = strTableName.Substring(tablePrefix.Length, strTableName.Length - tablePrefix.Length);

            // ----------------------------------
            // Create an "edit" type user control
            // ----------------------------------
            // The .Usercontrol file
            string strCode = GetAscxEditFile(strTableName);
            generatorFeedback.Exception = CreateFileFromString("UserControls\\AutoGenerated\\uc" + userControlName + "Edit.ascx", strCode);
            lines += CountLinesInString(strCode);

            // The .Usercontrol.Designer.cs file
            strCode = GetAscxEditDesignerFile(strTableName);
            generatorFeedback.Exception = CreateFileFromString("UserControls\\AutoGenerated\\uc" + userControlName + "Edit.ascx.designer.cs", strCode);
            lines += CountLinesInString(strCode);

            // The Usercontrol.cs file
            strCode = GetAscxEditClass(strTableName);
            generatorFeedback.Exception = CreateFileFromString("UserControls\\AutoGenerated\\uc" + userControlName + "Edit.ascx.cs", strCode);
            lines += CountLinesInString(strCode);

            // ----------------------------------
            // Create an "list" type user control
            // ----------------------------------
            // The .Usercontrol file
            strCode = GetAscxListFile(strTableName);
            generatorFeedback.Exception = CreateFileFromString("UserControls\\AutoGenerated\\uc" + userControlName + "List.ascx", strCode);
            lines += CountLinesInString(strCode);

            // The .Usercontrol.Designer.cs file
            strCode = GetAscxListDesignerFile(strTableName);
            generatorFeedback.Exception = CreateFileFromString("UserControls\\AutoGenerated\\uc" + userControlName + "List.ascx.designer.cs", strCode);
            lines += CountLinesInString(strCode);

            // The Usercontrol.cs file
            strCode = GetAscxListClass(strTableName);
            generatorFeedback.Exception = CreateFileFromString("UserControls\\AutoGenerated\\uc" + userControlName + "List.ascx.cs", strCode);
            lines += CountLinesInString(strCode);

            generatorFeedback.Lines = lines;

            return generatorFeedback;
        }

        public static string GetAscxEditFile(string strTableName)
        {
            string strCode = String.Empty;
            DbTable dbTable = new DbTable(strTableName, _tablePrefix);

            strCode += "<%@ Control Language=\"C#\" AutoEventWireup=\"true\" CodeBehind=\"uc" + dbTable.ClassName + "Edit.ascx.cs\" Inherits=\"" + Dry.ProjectName + ".UserControls.uc" + dbTable.ClassName + "Edit\" %>";
            strCode += "Edit" + _strNewLine;

            return strCode;
        }

        public static string GetAscxEditDesignerFile(string strTableName)
        {
            string strCode = string.Empty;
            DbTable dbTable = new DbTable(strTableName, _tablePrefix);

            strCode += "//------------------------------------------------------------------------------" + _strNewLine;
            strCode += "// <auto-generated>" + _strNewLine;
            strCode += "//     This code was generated by a tool." + _strNewLine;
            strCode += "//" + _strNewLine;
            strCode += "//     Changes to this file may cause incorrect behavior and will be lost if" + _strNewLine;
            strCode += "//     the code is regenerated. " + _strNewLine;
            strCode += "// </auto-generated>" + _strNewLine;
            strCode += "//------------------------------------------------------------------------------" + _strNewLine;
            strCode += "" + _strNewLine;
            strCode += "namespace " + Dry.ProjectName + " {" + _strNewLine;
            strCode += "" + _strNewLine;
            strCode += "" + _strNewLine;
            strCode += "    public partial class uc" + dbTable.ClassName + "Edit {" + _strNewLine;
            strCode += "" + _strNewLine;

            //strCode += AddDesignerControlCode("System.Web.UI.HtmlControls", "HtmlForm", "frmTaxibokning");

            strCode += "    }" + _strNewLine;
            strCode += "}" + _strNewLine;

            return strCode;
        }

        public static string GetAscxEditClass(string strTableName)
        {
            string strCode = String.Empty;

            strCode += GetFileHeader(Dry.ProjectName, "", "", "", "", "");
            DbTable dbTable = new DbTable(strTableName, _tablePrefix);

            strCode += "using System;" + _strNewLine;
            strCode += "using System.Collections.Generic;" + _strNewLine;
            strCode += "using System.Linq;" + _strNewLine;
            strCode += "using System.Web;" + _strNewLine;
            strCode += "using System.Web.UI;" + _strNewLine;
            strCode += "using System.Web.UI.WebControls;" + _strNewLine;
            strCode += "" + _strNewLine;
            strCode += "namespace " + Dry.ProjectName + ".UserControls" + _strNewLine;
            strCode += "{" + _strNewLine;
            strCode += "    public partial class uc" + dbTable.ClassName + "Edit : System.Web.UI.UserControl" + _strNewLine;
            strCode += "    {" + _strNewLine;
            strCode += "        protected void Page_Load(object sender, EventArgs e)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "    }" + _strNewLine;
            strCode += "}" + _strNewLine;

            return strCode;
        }

        public static string GetAscxListFile(string strTableName)
        {
            string strCode = String.Empty;
            DbTable dbTable = new DbTable(strTableName, _tablePrefix);

            strCode += "<%@ Control Language=\"C#\" AutoEventWireup=\"true\" CodeBehind=\"uc" + dbTable.ClassName + "List.ascx.cs\" Inherits=\"" + Dry.ProjectName + ".UserControls.uc" + dbTable.ClassName + "List\" %>" + _strNewLine + _strNewLine;

            // Generated by dryify
            strCode += "<asp:GridView ID=\"gv" + dbTable.ClassName + "List\" OnRowCommand=\"gv" + dbTable.ClassName + "List_RowCommand\" OnRowDataBound=\"gv" + dbTable.ClassName + "List_RowDataBound\" runat=\"server\" AutoGenerateColumns=\"false\" AllowPaging=\"false\" AllowSorting=\"false\">" + _strNewLine;
            strCode += "    <Columns>" + _strNewLine;
            strCode += "        <asp:TemplateField>" + _strNewLine;
            strCode += "            <ItemTemplate>" + _strNewLine;
            strCode += "                <asp:LinkButton ID=\"lbnView" + dbTable.ClassName + "\" runat=\"server\" CommandName=\"View" + dbTable.ClassName + "\" Text=\"View\" />" + _strNewLine;
            strCode += "            </ItemTemplate>" + _strNewLine;
            strCode += "        </asp:TemplateField>" + _strNewLine;
            strCode += "        " + _strNewLine;
            strCode += "        <asp:TemplateField>" + _strNewLine;
            strCode += "            <ItemTemplate>" + _strNewLine;
            strCode += "                <asp:LinkButton ID=\"lbnEdit" + dbTable.ClassName + "\" runat=\"server\" CommandName=\"Edit" + dbTable.ClassName + "\" Text=\"Edit\" />" + _strNewLine;
            strCode += "            </ItemTemplate>" + _strNewLine;
            strCode += "        </asp:TemplateField>" + _strNewLine;
            strCode += "        " + _strNewLine;

            // Add columns to the gridivew
            foreach (DbColumn dbColumn in dbTable.DbColumns)
            {
                strCode += "        <asp:BoundField DataField=\"" + dbColumn.ColumnName + "\" HeaderText=\"" + dbColumn.ColumnName + "\" />" + _strNewLine;
            }
            
            strCode += "        " + _strNewLine;
            strCode += "        <asp:TemplateField>" + _strNewLine;
            strCode += "            <ItemTemplate>" + _strNewLine;
            strCode += "                <asp:LinkButton ID=\"lbnDelete" + dbTable.ClassName + "\" runat=\"server\" CommandName=\"Delete" + dbTable.ClassName + "\" Text=\"Delete\" />" + _strNewLine;
            strCode += "            </ItemTemplate>" + _strNewLine;
            strCode += "        </asp:TemplateField>" + _strNewLine;
            strCode += "    </Columns>" + _strNewLine;
            strCode += "</asp:GridView>" + _strNewLine;

            return strCode;
        }

        public static string GetAscxListDesignerFile(string strTableName)
        {
            string strCode = string.Empty;
            DbTable dbTable = new DbTable(strTableName, _tablePrefix);

            strCode += "//------------------------------------------------------------------------------" + _strNewLine;
            strCode += "// <auto-generated>" + _strNewLine;
            strCode += "//     This code was generated by a tool." + _strNewLine;
            strCode += "//" + _strNewLine;
            strCode += "//     Changes to this file may cause incorrect behavior and will be lost if" + _strNewLine;
            strCode += "//     the code is regenerated. " + _strNewLine;
            strCode += "// </auto-generated>" + _strNewLine;
            strCode += "//------------------------------------------------------------------------------" + _strNewLine;
            strCode += "" + _strNewLine;
            strCode += "namespace " + Dry.ProjectName + ".UserControls {" + _strNewLine;
            strCode += "" + _strNewLine;
            strCode += "" + _strNewLine;
            strCode += "    public partial class uc" + dbTable.ClassName + "List {" + _strNewLine;
            strCode += "    " + _strNewLine;

            // Generated by dryify
            strCode += "        /// <summary>" + _strNewLine;
            strCode += "        /// gv" + dbTable.ClassName + "List control." + _strNewLine;
            strCode += "        /// </summary>" + _strNewLine;
            strCode += "        /// <remarks>" + _strNewLine;
            strCode += "        /// Auto-generated field." + _strNewLine;
            strCode += "        /// To modify move field declaration from designer file to code-behind file." + _strNewLine;
            strCode += "        /// </remarks>" + _strNewLine;
            strCode += "        protected global::System.Web.UI.WebControls.GridView gv" + dbTable.ClassName + "List;" + _strNewLine;

            strCode += "    }" + _strNewLine;
            strCode += "}" + _strNewLine;

            return strCode;
        }

        public static string GetAscxListClass(string strTableName)
        {
            string strCode = String.Empty;
            DbTable dbTable = new DbTable(strTableName, _tablePrefix);

            strCode += GetFileHeader(Dry.ProjectName, "", "", "", "", "");

            // Generated by dryify
            strCode += "using System;" + _strNewLine;
            strCode += "using System.Collections.Generic;" + _strNewLine;
            strCode += "using System.Linq;" + _strNewLine;
            strCode += "using System.Web;" + _strNewLine;
            strCode += "using System.Web.UI;" + _strNewLine;
            strCode += "using System.Web.UI.WebControls;" + _strNewLine;
            strCode += "using Backend.BO;" + _strNewLine;
            strCode += "using Backend.BLL;" + _strNewLine;
            strCode += "using Backend.DAL;" + _strNewLine;
            strCode += "" + _strNewLine;
            strCode += "namespace Frontend.UserControls" + _strNewLine;
            strCode += "{" + _strNewLine;
            strCode += "    public partial class uc" + dbTable.ClassName + "List : System.Web.UI.UserControl" + _strNewLine;
            strCode += "    {" + _strNewLine;
            strCode += "        public event GridViewCommandEventHandler Command;" + _strNewLine;
            strCode += "        " + _strNewLine;
            strCode += "        /// <summary>" + _strNewLine;
            strCode += "        /// Data source to bind the list with" + _strNewLine;
            strCode += "        /// </summary>" + _strNewLine;
            strCode += "        public List<" + dbTable.ClassName + "BO> DataSource" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            get { return ViewState[\"DataSource\"] != null ? (List<" + dbTable.ClassName + "BO>) ViewState[\"DataSource\"] : null; }" + _strNewLine;
            strCode += "            set { ViewState[\"DataSource\"] = value; }" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "        " + _strNewLine;
            strCode += "        protected void Page_Load(object sender, EventArgs e)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            if(!IsPostBack)" + _strNewLine;
            strCode += "            {" + _strNewLine;
            strCode += "                " + _strNewLine;
            strCode += "            }" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "        " + _strNewLine;
            strCode += "        /// <summary>" + _strNewLine;
            strCode += "        /// Databind the datasource to the list" + _strNewLine;
            strCode += "        /// </summary>" + _strNewLine;
            strCode += "        public override void DataBind()" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            gv" + dbTable.ClassName + "List.DataSource = DataSource;" + _strNewLine;
            strCode += "            gv" + dbTable.ClassName + "List.DataBind();" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "        " + _strNewLine;
            strCode += "        protected void gv" + dbTable.ClassName + "List_RowDataBound(object sender, GridViewRowEventArgs e)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            if(e.Row.RowType == DataControlRowType.DataRow)" + _strNewLine;
            strCode += "            {" + _strNewLine;
            strCode += "                " + dbTable.ClassName + "BO userBo = (" + dbTable.ClassName + "BO) e.Row.DataItem;" + _strNewLine;
            strCode += "                " + _strNewLine;
            strCode += "                LinkButton lbnEdit" + dbTable.ClassName + " = (LinkButton) e.Row.FindControl(\"lbnEdit" + dbTable.ClassName + "\");" + _strNewLine;
            strCode += "                LinkButton lbnView" + dbTable.ClassName + " = (LinkButton)e.Row.FindControl(\"lbnView" + dbTable.ClassName + "\");" + _strNewLine;
            strCode += "                LinkButton lbnDelete" + dbTable.ClassName + " = (LinkButton)e.Row.FindControl(\"lbnDelete" + dbTable.ClassName + "\");" + _strNewLine;
            strCode += "                " + _strNewLine;
            strCode += "                lbnEdit" + dbTable.ClassName + ".CommandArgument = userBo." + dbTable.ClassName + "Id.ToString();" + _strNewLine;
            strCode += "                lbnView" + dbTable.ClassName + ".CommandArgument = userBo." + dbTable.ClassName + "Id.ToString();" + _strNewLine;
            strCode += "                lbnDelete" + dbTable.ClassName + ".CommandArgument = userBo." + dbTable.ClassName + "Id.ToString();" + _strNewLine;
            strCode += "            }" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "        " + _strNewLine;
            strCode += "        protected void gv" + dbTable.ClassName + "List_RowCommand(object sender, GridViewCommandEventArgs e)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            switch (e.CommandName)" + _strNewLine;
            strCode += "            {" + _strNewLine;
            strCode += "                case \"View" + dbTable.ClassName + "\":" + _strNewLine;
            strCode += "                    if (Command != null)" + _strNewLine;
            strCode += "                        Command(sender, e);" + _strNewLine;
            strCode += "                    break;" + _strNewLine;
            strCode += "                " + _strNewLine;
            strCode += "                case \"Edit" + dbTable.ClassName + "\":" + _strNewLine;
            strCode += "                    if (Command != null)" + _strNewLine;
            strCode += "                        Command(sender, e);" + _strNewLine;
            strCode += "                    break;" + _strNewLine;
            strCode += "                " + _strNewLine;
            strCode += "                case \"Delete" + dbTable.ClassName + "\":" + _strNewLine;
            strCode += "                    " + dbTable.ClassName + "BLL.Delete(" + dbTable.ClassName + "BLL.GetById(int.Parse(e.CommandArgument.ToString())));" + _strNewLine;
            strCode += "                    " + _strNewLine;
            strCode += "                    if (Command != null)" + _strNewLine;
            strCode += "                        Command(sender, e);" + _strNewLine;
            strCode += "                    break;" + _strNewLine;
            strCode += "            }" + _strNewLine;
            strCode += "        }" + _strNewLine;

            strCode += "    }" + _strNewLine;
            strCode += "}" + _strNewLine;
            strCode += "" + _strNewLine;

            return strCode;
        }

        private static string AddDesignerControlCode(string controlNamespace, string controlType, string controlName)
        {
            string strCode = string.Empty;
            //DbTable dbTable = new DbTable(strTableName, _tablePrefix);

            strCode += "            /// <summary>" + _strNewLine;
            strCode += "            /// head control." + _strNewLine;
            strCode += "            /// </summary>" + _strNewLine;
            strCode += "            /// <remarks>" + _strNewLine;
            strCode += "            /// Auto-generated field." + _strNewLine;
            strCode += "            /// To modify move field declaration from designer file to code-behind file." + _strNewLine;
            strCode += "            /// </remarks>" + _strNewLine;
            strCode += "            protected global::" + controlNamespace + "." + controlType + " " + controlName + ";" + _strNewLine;

            return strCode;
        }

        protected static DataTable GetRelationTable(string strTableName, bool distinct)
        {
            // Get table relations
            Database db = GetDatabase();
            DbCommand dbCommand = db.GetSqlStringCommand("exec sp_fkeys @pktable_name = '" + strTableName + "'");

            string[] columnNameFk = new[] { "PKTABLE_NAME", "FKCOLUMN_NAME", "PKCOLUMN_NAME" };
            string[] columnNamePk = new[] { "FKTABLE_NAME", "FKCOLUMN_NAME", "PKCOLUMN_NAME" };
            string[] columnNameFinal = new[] { "TABLE", "COLUMN", "PKCOLUMN" };

            DataTable dataTablePk = db.ExecuteDataSet(dbCommand).Tables[0].DefaultView.ToTable(distinct, columnNamePk);
            dataTablePk.Columns[0].ColumnName = "TABLE";
            dataTablePk.Columns[1].ColumnName = "COLUMN";
            dataTablePk.Columns[2].ColumnName = "PKCOLUMN";

            dbCommand = db.GetSqlStringCommand("exec sp_fkeys @fktable_name = '" + strTableName + "'");

            DataTable dataTableFk = db.ExecuteDataSet(dbCommand).Tables[0].DefaultView.ToTable(distinct, columnNameFk);
            dataTableFk.Columns[0].ColumnName = "TABLE";
            dataTableFk.Columns[1].ColumnName = "COLUMN";
            dataTableFk.Columns[2].ColumnName = "PKCOLUMN";

            dataTableFk.Merge(dataTablePk);
            DataTable dataTableFinal = dataTableFk.DefaultView.ToTable(true, columnNameFinal);

            return dataTableFinal;
        }
    }
}
